﻿using System;
using System.Collections.Generic;
using UnityEngine;
using VoxelBlock.VoxelBlock3D;
using VoxelBlock;using Vector3Int = VoxelBlock.Vector3Int;

public class OperationImplementSliceRemove : OperationImplement
{

    /// <summary>
    /// 尝试性添加或删除
    /// </summary>
    Dictionary<Vector3Int, Voxel3D> attemptDictionaryVoxels = new Dictionary<Vector3Int, Voxel3D>();

    int oldlayer = 0;

    int sliceLayer = 0;

    int startLayer = 0;
    GameObject meshSliceCollider;
    Transform mainCameraY;


    /// <summary>
    /// 一样的颜色才可以
    /// </summary>
    int mSliceUVxy;
    /// <summary>
    /// 对一片进行操作时保存6个方向中的一个
    /// </summary>
    VoxelDirection sliceDirection;

    Func<VoxelDirection> SetSliceDirection;

    /// <summary>
    /// 对一片进行操作时保存6个方向中的一个
    /// </summary>
    Vector3Int MeshSliceXYZ = new Vector3Int();
    Dictionary<Vector3Int, int> mSlicesBlocks = new Dictionary<Vector3Int, int>();
    //Dictionary<Vector3Int, int> mSlicesBlocks2 = new Dictionary<Vector3Int, int>();
    
    StartSliceArg startSliceArg = new StartSliceArg();

    public OperationImplementSliceRemove(GameObject meshSliceCollider
        , Transform mainCameraY, Func<VoxelDirection> setSliceDirection
        ) 
    {
        this.meshSliceCollider = meshSliceCollider;
        this.mainCameraY = mainCameraY;
        this.SetSliceDirection = setSliceDirection;
    }

    public override void Start(StartArg arg)
    {
        startSliceArg = arg.startSliceArg;
        base.Start(arg);

        StartMethod(arg.StartPosition);
    }

    private void StartMethod(Vector3Int StartPosition)
    {
        sliceDirection = SetSliceDirection();
        Vector3 bPosition = StartPosition;
        meshSliceCollider.gameObject.SetActive(true);
        meshSliceCollider.transform.position = bPosition;// new Vector3();
        switch (sliceDirection)
        {
            case VoxelDirection.Right:
                //bPosition -= new Vector3(1, 0, 0);
                meshSliceCollider.transform.eulerAngles = new Vector3(90, 0, 0);
                startLayer = (int)bPosition.x;
                break;
            case VoxelDirection.Left:
                //bPosition += new Vector3(1, 0, 0);
                startLayer = (int)bPosition.x;
                meshSliceCollider.transform.eulerAngles = new Vector3(90, 0, 0);
                break;
            case VoxelDirection.Up:
                //bPosition -= new Vector3(0, 1, 0);
                startLayer = (int)bPosition.y;
                meshSliceCollider.transform.eulerAngles = new Vector3(0, mainCameraY.eulerAngles.y, 0);
                break;
            case VoxelDirection.Down:
                //bPosition += new Vector3(0, 1, 0);
                startLayer = (int)bPosition.y;
                meshSliceCollider.transform.eulerAngles = new Vector3(0, mainCameraY.eulerAngles.y, 0);
                break;
            case VoxelDirection.Front:
                //bPosition -= new Vector3(0, 0, 1);
                meshSliceCollider.transform.eulerAngles = new Vector3(90, 0, 0);
                startLayer = (int)bPosition.z;
                break;
            case VoxelDirection.Break:
                //bPosition += new Vector3(0, 0, 1);
                meshSliceCollider.transform.eulerAngles = new Vector3(90, 0, 0);
                startLayer = (int)bPosition.z;
                break;
            default:
                break;
        }

        if (!nowDrawVoxel3DCore.allVoxels.ContainsKey(bPosition))
        {
            return;
        }
        mSlicesBlocks = new Dictionary<Vector3Int, int>();
        mSliceUVxy = nowDrawVoxel3DCore.allVoxels[bPosition].uvKey;
        //BasicAlgorithm.GetSliceBlock(mSlicesBlocks, sliceDirection, bPosition, mSliceUVxy, nowDrawVoxel3DCore.allVoxels);
        BasicAlgorithm.GetSliceBlock(mSlicesBlocks, sliceDirection, bPosition, mSliceUVxy, nowDrawVoxel3DCore.allVoxels, startSliceArg.Is8, startSliceArg.GetColor);

        switch (sliceDirection)
        {
            case VoxelDirection.Right:
                MeshSliceXYZ = new Vector3Int(1, 0, 0);
                break;
            case VoxelDirection.Left:
                MeshSliceXYZ = new Vector3Int(-1, 0, 0);
                break;
            case VoxelDirection.Up:
                MeshSliceXYZ = new Vector3Int(0, 1, 0);
                break;
            case VoxelDirection.Down:
                MeshSliceXYZ = new Vector3Int(0, -1, 0);
                break;
            case VoxelDirection.Front:
                MeshSliceXYZ = new Vector3Int(0, 0, 1);
                break;
            case VoxelDirection.Break:
                MeshSliceXYZ = new Vector3Int(0, 0, -1);
                break;
        }
        switch (sliceDirection)
        {
            case VoxelDirection.Right:
                oldlayer = (int)bPosition.x - startLayer;
                break;
            case VoxelDirection.Left:
                oldlayer = -(int)bPosition.x + startLayer;
                break;
            case VoxelDirection.Up:
                oldlayer = (int)bPosition.y - startLayer;
                break;
            case VoxelDirection.Down:
                oldlayer = -(int)bPosition.y + startLayer;
                break;
            case VoxelDirection.Front:
                oldlayer = (int)bPosition.z - startLayer;
                break;
            case VoxelDirection.Break:
                oldlayer = -(int)bPosition.z + startLayer;
                break;
        }
        //oldlayer--;
        Vector3Int[] array = new Vector3Int[mSlicesBlocks.Count];
        int index = 0;
        foreach (Vector3Int position in mSlicesBlocks.Keys)
        {
            Voxel3D voxel;
            if (nowDrawVoxel3DCore.allVoxels.TryGetValue(position, out voxel))
            {
                array[index] = position;
                attemptDictionaryVoxels[position] = voxel;
                index++;
            }
        }
        nowDrawVoxel3DCore.DrawRemoveBlock(array);
    }

    public override void Run(RunArg arg)
    {
        Vector3Int bPosition = arg.nowSelectPosition;
        switch (sliceDirection)
        {
            case VoxelDirection.Right:
                sliceLayer = (int)bPosition.x - startLayer;
                break;
            case VoxelDirection.Left:
                sliceLayer = -(int)bPosition.x + startLayer;
                break;
            case VoxelDirection.Up:
                sliceLayer = (int)bPosition.y - startLayer;
                break;
            case VoxelDirection.Down:
                sliceLayer = -(int)bPosition.y + startLayer;
                break;
            case VoxelDirection.Front:
                sliceLayer = (int)bPosition.z - startLayer;
                break;
            case VoxelDirection.Break:
                sliceLayer = -(int)bPosition.z + startLayer;
                break;
        }
        sliceLayer--;
        if (oldlayer == sliceLayer || sliceLayer >= 0)
        {
            return;
        }

        if (oldlayer < sliceLayer)
        {
            List<Voxel3D> arrayVoxel3D = new List<Voxel3D>(mSlicesBlocks.Count * (sliceLayer - oldlayer));
            for (int i = oldlayer + 1; i <= sliceLayer; i++)
            {
                foreach (Vector3Int position in mSlicesBlocks.Keys)
                {
                    Voxel3D voxel;
                    Vector3Int key = position + MeshSliceXYZ * i;
                    if (attemptDictionaryVoxels.TryGetValue(key, out voxel))
                    {
                        arrayVoxel3D.Add(voxel);
                        attemptDictionaryVoxels.Remove(key);
                    }
                }
            }
            nowDrawVoxel3DCore.DrawAddBlock(arrayVoxel3D);
        }
        else
        {
            List<Vector3Int> arrayVector3Int = new List<Vector3Int>(mSlicesBlocks.Count * (oldlayer - sliceLayer));
            for (int i = oldlayer; i >= sliceLayer + 1; i--)
            {
                foreach (Vector3Int position in mSlicesBlocks.Keys)
                {
                    Vector3Int key = position + MeshSliceXYZ * i;
                    Voxel3D voxel;
                    if (nowDrawVoxel3DCore.allVoxels.TryGetValue(key, out voxel))
                    {
                        arrayVector3Int.Add(key);
                        attemptDictionaryVoxels[key] = voxel;
                    }
                }
            }
            nowDrawVoxel3DCore.DrawRemoveBlock(arrayVector3Int);
        }

        oldlayer = sliceLayer;

    }

    public override void Over(OverArg arg)
    {
        if (isStop)
        {

        }
        else
        {
            StartMethod(arg.gestureStartPosition);
            meshSliceCollider.gameObject.SetActive(false);
            List<SimpleVoxel> arrayVoxel3D = new List<SimpleVoxel>(attemptDictionaryVoxels.Count);
            foreach (var item in attemptDictionaryVoxels.Values)
            {
                arrayVoxel3D.Add(new SimpleVoxel(item.worldPosition, item.uvKey, item.selectKey));
            }
            if (arrayVoxel3D.Count > 0)
            {
                proxy.Write(VoxelCategories.Operation.Remove, arrayVoxel3D, historyRecordBreakList);
                historyRecordBreakList = new List<SimpleVoxel>();
                //historyRecordFrontList = new List<SimpleVoxel>();
            }
            attemptDictionaryVoxels.Clear();
        }
    }

}


